// input为第二个参数设置
let {pages, done, sort, options} = input;

// Error Handling
if (!pages && pages!="") {
    dv.span('> [!ERROR] Missing pages parameter\n> \n> Please set the pages parameter like\n> \n> `pages: ""`');
    return false;
};

// Get, Set, Eval Pages
if (pages == "") {
    var tasks = dv.pages().file.tasks;
} else {
    if (pages.startsWith("dv.pages")) { 
        var tasks = eval(pages);
    } else {
        var tasks = dv.pages(pages).file.tasks;
    }
}
if (!options) {options = ""};
if (!sort) {sort = "!t.completed && Object.keys(t.happens).find(key => t.happens[key] === timelineDates[i].toString())"};

// 时间线有多少个日期：具体的日期，如果没有的话，则产生一个未知日期，任务后面没有跟具体日期的，都使用此unknown
var timelineDates = [];
// 时间
var tid = (new Date()).getTime();
var today = moment().format("YYYY-MM-DD");

// Set Root
const rootNode = dv.el("div", "", {cls: "taskido "+options, attr: {id: "taskido"+tid}});

// Icons
var doneIcon = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 11 12 14 22 4"></polyline><path d="M21 12v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11"></path></svg>';
var dueIcon = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="4" width="18" height="18" rx="2" ry="2"></rect><line x1="16" y1="2" x2="16" y2="6"></line><line x1="8" y1="2" x2="8" y2="6"></line><line x1="3" y1="10" x2="21" y2="10"></line></svg>';
var scheduledIcon = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 22h14"></path><path d="M5 2h14"></path><path d="M17 22v-4.172a2 2 0 0 0-.586-1.414L12 12l-4.414 4.414A2 2 0 0 0 7 17.828V22"></path><path d="M7 2v4.172a2 2 0 0 0 .586 1.414L12 12l4.414-4.414A2 2 0 0 0 17 6.172V2"></path></svg>';
var startIcon = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M17.8 19.2 16 11l3.5-3.5C21 6 21.5 4 21 3c-1-.5-3 0-4.5 1.5L13 8 4.8 6.2c-.5-.1-.9.1-1.1.5l-.3.5c-.2.5-.1 1 .3 1.3L9 12l-2 3H4l-1 1 3 2 2 3 1-1v-3l3-2 3.5 5.3c.3.4.8.5 1.3.3l.5-.2c.4-.3.6-.7.5-1.2z"></path></svg>';
var overdueIcon = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3Z"></path><line x1="12" y1="9" x2="12" y2="13"></line><line x1="12" y1="17" x2="12.01" y2="17"></line></svg>';
var processIcon = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 6H5a2 2 0 0 0-2 2v3a2 2 0 0 0 2 2h13l4-3.5L18 6Z"></path><path d="M12 13v9"></path><path d="M12 2v4"></path></svg>';
var dailynoteIcon = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5L14.5 2z"></path><polyline points="14 2 14 8 20 8"></polyline></svg>';
var dailytaskIcon = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect></svg>';
var todoIcon = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect><line x1="12" y1="8" x2="12" y2="16"></line><line x1="8" y1="12" x2="16" y2="12"></line></svg>';
var addIcon = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect><line x1="12" y1="8" x2="12" y2="16"></line><line x1="8" y1="12" x2="16" y2="12"></line></svg>';
var tagIcon = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2H2v10l9.29 9.29c.94.94 2.48.94 3.42 0l6.58-6.58c.94-.94.94-2.48 0-3.42L12 2Z"></path><path d="M7 7h.01"></path></svg>';
var repeatIcon = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m17 2 4 4-4 4"></path><path d="M3 11v-1a4 4 0 0 1 4-4h14"></path><path d="m7 22-4-4 4-4"></path><path d="M21 13v1a4 4 0 0 1-4 4H3"></path></svg>';
var priorityIcon = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"></circle><line x1="12" y1="16" x2="12" y2="12"></line><line x1="12" y1="8" x2="12.01" y2="8"></line></svg>';
var starIcon = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5L14.5 2z"></path><polyline points="14 2 14 8 20 8"></polyline></svg>';

// 定义任务数量相关内容
var overdueCount = 0;
var doneCount = 0;
var processCount = 0;

// Initialze
getMeta(tasks);
getTimeline(tasks);
// setEvents();

// 任务状态定义：
// happens["process"] = 所有正在处理的
// happens["due'] = 所有超过期限的
// happens["done"] 所有已完成的

// 这里为遍历所有任务，然后进行统计
// year->下面有多个details, 每个 details就对应一个日期下面的所有任务，每个任务对应相应的链接及内容
// 先进行日期统计，然后过滤
// 找出每个任务后面存在的最后一个日期
function getMeta(tasks) {
    var hasUnknownDate = false;
    for (i=0;i<tasks.length;i++) {
        let happens = {}; // 字典，除了完成的其他都是未完成，未完成的查看是那个状态
        var taskText = tasks[i].text;

        // var taskFile = getFilename(tasks[i].path); // 任务所在文件，这里获取文件名称, 对于真实的路径还是需要使用task[i].path
        // 内容是否有 YYYY-MM-DD， 有的花代表是dailyTaskMatch,这里没有啥意义
        // var dailyTaskMatch = taskText.match(/(\d{4}\-\d{2}\-\d{2})/);
        // 不关心此
        // var dailyNoteMatch = taskFile.match(eval(dailyNoteRegEx));
        // 这里应该主要是为没有匹配到时间的任务添加一个时间点，应该直接获取
        // if (dailyNoteMatch && tasks[i].completed == false) {
        //     if(!dailyTaskMatch) {
        //         tasks[i].dailytask = moment(dailyNoteMatch[1], dailyNoteFormat).format("YYYY-MM-DD");
        //         happens["dailytask"] = moment(dailyNoteMatch[1], dailyNoteFormat).format("YYYY-MM-DD");
        //         timelineDates.push(moment(dailyNoteMatch[1], dailyNoteFormat).format("YYYY-MM-DD"));
        //     };
        // };

        // var taskText = "sdcv 命令行的补全 ➕2023-06-13";
        // var dueMatch = taskText.match(/\➕\W?(\d{4}\-\d{2}\-\d{2})/);
        // dueMatch结果为 ➕2023-06-13, 2023-06-13

        var findDate = 0;
        var unknownDoneDate = true;

        // 首先查看任务是否完成
        // 完成日期任务, 下面的done决定是否显示已完成任务
        var doneMatch = taskText.match(/\✅\W?(\d{4}\-\d{2}\-\d{2})/);
        if (doneMatch) {
            ++findDate;
            unknownDoneDate = false;
            tasks[i].text = tasks[i].text.replace(doneMatch[0], "");
            if (done == true) {
                timelineDates.push(doneMatch[1]); // 个数
                happens["done"] = doneMatch[1];
            }
        } else {
            // 没有此特殊标记，是否有其他日期
            if (done == true && tasks[i].completed == true) {
                happens["done"] = today;
            }
        }

        var isDurTask = false;
        // 如果是逾期的则不计入其他日期
        // 截止日期任务 var now = moment()
        // 下面匹配了日期， 其中 dueMatch[1]为具体的日期对象
        var dueMatch = taskText.match(/\🗓️\W?(\d{4}\-\d{2}\-\d{2})/);
        if (dueMatch) {
            ++findDate;
            tasks[i].text = tasks[i].text.replace(dueMatch[0], "");
            if (task[i].completed) {
                if (done == true && unknownDoneDate == true) {
                    // 前面的日期未知
                    happens["done"] = dueMatch[1];
                    timelineDates.push(dueMatch[1]);
                }
            } else {
                timelineDates.push(dueMatch[1]); // 添加进修时一个日期
                // 逾期
                if (dueMatch[1] < moment().format("YYYY-MM-DD") ) {
                    happens["overdue"] = dueMatch[1];
                    isDurTask = true;
                } else {
                    happens["process"] = dueMatch[1];
                }
            }
        }

        if (isDurTask == true) {
            ++overdueCount;
        } else {
            if (tasks[i].completed == true) {
                ++doneCount;
            } else {
                ++processCount;
            }
        }

        // 刚创建任务的状态
        var createMatch = taskText.match(/\➕\W?(\d{4}\-\d{2}\-\d{2})/);
        if (createMatch) {
            ++findDate;
            tasks[i].text = tasks[i].text.replace(createMatch[0], "");
            if (tasks[i].completed) {
                if (done == true && unknownDoneDate == true) {
                    // 前面的日期未知
                    happens["done"] = createMatch[1];
                    timelineDates.push(createMatch[1]); // 添加进一个日期
                }
            } else {
                if (isDurTask == false) {
                    happens["process"] = createMatch[1];
                    timelineDates.push(createMatch[1]); // 添加进一个日期
                }
            }
        }

        // 开始日期任务
        var startMatch = taskText.match(/\🛫\W?(\d{4}\-\d{2}\-\d{2})/);
        if (startMatch) {
            ++findDate;
            tasks[i].text = tasks[i].text.replace(startMatch[0], "");
            if(tasks[i].completed) {
                if (done == true && unknownDoneDate == true) {
                    // 前面的日期未知
                    happens["done"] = startMatch[1];
                    timelineDates.push(startMatch[1]); // 添加进行一个任务日期点
                }
            } else {
                if (isDurTask == false) {
                    happens["process"] = startMatch[1];
                    timelineDates.push(startMatch[1]); // 添加进行一个任务日期点
                }
            }
        }

        // 计划日期任务
        var scheduledMatch = taskText.match(/\⏳\W?(\d{4}\-\d{2}\-\d{2})/);
        if (scheduledMatch) {
            ++findDate;
            tasks[i].text = tasks[i].text.replace(scheduledMatch[0], "");
            if (tasks[i].completed) {
                if (done == true && unknownDoneDate == true) {
                    // 前面的日期未知
                    happens["done"] = scheduledMatch[1];
                    timelineDates.push(scheduledMatch[1]);
                }
            } else {
                if (isDurTask == false) {
                    happens["process"] = scheduledMatch[1];
                    timelineDates.push(scheduledMatch[1]);
                }
            }
        }

        // 需要确定此任务是否有未知的时间
        if (findDate == 0) {
            hasUnknownDate = true;
            if (tasks[i].completed) {
                if (done == true) {
                    // 前面的日期未知
                    happens["done"] = today;
                }
            } else {
                if (isDurTask == false) {
                    happens["process"] = today;
                }
            }
        }

        // 移除任务里面的链接信息
        tasks[i].text = tasks[i].text.replaceAll("[[","");
        tasks[i].text = tasks[i].text.replaceAll("]]","");
        // 替换 [ ] 相关内容
        tasks[i].text = tasks[i].text.replace(/\[.*?\]/gm,"");
        // 任务那个阶段
        tasks[i].happens = happens;
    };
    //timelineDates.push(today);
    timelineDates = [...new Set(timelineDates)].sort();
    if (hasUnknownDate && (timelineDates.contains(today) == false)) {
        timelineDates.push(today);
    }
};

function setEvents() {
    rootNode.querySelectorAll('.counter').forEach(cnt => cnt.addEventListener('click', (() => {
        var activeFocus = Array.from(rootNode.classList).filter(c=>c.endsWith("Focus") && !c.startsWith("today"));
        if (activeFocus == cnt.id+"Focus") {
            rootNode.classList.remove(activeFocus);
            return false;
        };
        rootNode.classList.remove.apply(rootNode.classList, Array.from(rootNode.classList).filter(c=>c.endsWith("Focus") && !c.startsWith("today")));
        rootNode.classList.add(cnt.id+"Focus");
    })));
    rootNode.querySelector('.todayHeader').addEventListener('click', (() => {
        rootNode.classList.toggle("todayFocus");
    }));
};

function getFilename(path) {
    var filename = path.match(/^(?:.*\/)?([^\/]+?|)(?=(?:\.[^\/.]*)?$)/)[1];
    return filename;
};

function getMetaFromNote(task, metaName) {
    var meta = dv.pages('"'+task.link.path+'"')[metaName][0];
    if (meta) { return meta } else { return "" };
};

function momentToRegex(momentFormat) {
    momentFormat = momentFormat.replaceAll(".", "\\.");
    momentFormat = momentFormat.replaceAll(",", "\\,");
    momentFormat = momentFormat.replaceAll("-", "\\-");
    momentFormat = momentFormat.replaceAll(":", "\\:");
    momentFormat = momentFormat.replaceAll(" ", "\\s");

    momentFormat = momentFormat.replace("dddd", "\\w{1,}");
    momentFormat = momentFormat.replace("ddd", "\\w{1,3}");
    momentFormat = momentFormat.replace("dd", "\\w{2}");
    momentFormat = momentFormat.replace("d", "\\d{1}");

    momentFormat = momentFormat.replace("YYYY", "\\d{4}");
    momentFormat = momentFormat.replace("YY", "\\d{2}");

    momentFormat = momentFormat.replace("MMMM", "\\w{1,}");
    momentFormat = momentFormat.replace("MMM", "\\w{3}");
    momentFormat = momentFormat.replace("MM", "\\d{2}");

    momentFormat = momentFormat.replace("DDDD", "\\d{3}");
    momentFormat = momentFormat.replace("DDD", "\\d{1,3}");
    momentFormat = momentFormat.replace("DD", "\\d{2}");
    momentFormat = momentFormat.replace("D", "\\d{1,2}");

    momentFormat = momentFormat.replace("ww", "\\d{1,2}");

    regEx = "/^(" + momentFormat + ")$/";

    return regEx;
};

// 生成时间线，重点
// year->date+relative->每个任务的情况
function getTimeline(tasks) {
    // 最后处理日期 unknown
    var lastYear = null;
    // 这里的timelineDates已经是排过序的
    let tmDatesLen = timelineDates.length - 1;
    for (i=0; i<=tmDatesLen; i++) {
        // 找出日期与当前要排列的内容
        var tasksFiltered = tasks.filter(t=>Object.values(t.happens).includes(timelineDates[i].toString())).sort(t=> eval(sort));
        if (0 == tasksFiltered.length) {
            continue;
        }

        // 相对于当前时间的一个格式
        var relative = moment(timelineDates[i].toString()).fromNow();
        // 日期
        var date = moment(timelineDates[i].toString()).format("MM-DD ddd") // 日期
        var year = moment(timelineDates[i].toString()).format("YYYY"); // 年份
        // 任务所属阶段类型
        var detailsCls = "";
        var content = "";

        // Add Year Section
        if (year != lastYear) {
            lastYear = year;
            cls = moment().format("YYYY") == year ? "current" : "";
            rootNode.querySelector("span").appendChild(dv.el("div", year, {cls: "year " + cls}));
        };

        // 对上面的过滤项执行下面的操作
        // 这里是具体的任务处理， 处理tasksFiltered, 对其中的每一项进行下面的处理
        tasksFiltered.forEach(function(item) {
            var file = getFilename(item.path); // 文件名称
            var link = item.link.path.replace("'", "&apos;"); // 链接
            var text = item.text; // 显示内容
            var info = ""; // tag 显示信息打包后的
            var color = getMetaFromNote(item, "color"); // 获取颜色
            // 属于那一类型任务
            var cls = Object.keys(item.happens).find(key => item.happens[key] === timelineDates[i].toString());

            // 任务的相关tag
            item.tags.forEach(function(tag) {
                var tagText = tag.replace("#","");
                var hexColorMatch = tag.match(/([a-fA-F0-9]{6}|[a-fA-F0-9]{3})\/(.*)/);
                if (hexColorMatch) {
                    var style = "style='--tag-color:#" + hexColorMatch[1] + ";--tag-background:#" + hexColorMatch[1] + "1a'";
                    tagText = hexColorMatch[2];
                };
                info += "<div class='tag' " + style + "><div class='icon'>" + tagIcon + "</div><div class='label'>" + tagText + "</div></div>";
                text = text.replace(tag, "");
            });

            // 这里添加详细的内容，主要是任务相关
            var task = "<a class='internal-link' href='" + link + "'><div class='task " + cls + "' style='--task-color:" + color + "'><div class='timeline'><div class='icon'>" + eval(cls+"Icon") + "</div><div class='stripe'></div></div><div class='lines'><div class='line'><div class='file'>" + file + "</div></div><div class='line'>" + info + "</div><div class='content'>" + text + "</div></div></div></a>";
            content += task;
        });

        // 最后一项时需要添加此
        if (i == tmDatesLen) {
            // 前面统计所有的任务，然后这里使用使用，
            detailsCls += "today";
            if (processCount == 0 && overdueCount == 0) {
                var motivation = "☕️ 哇，空闲的一天!"
            } else if (processCount >= 8) {
                var motivation = "🥯 我去，这么多任务，啥时候是头啊!"
            } else {
                var motivation = "🚧 边享受边做吧!"
            }

            // 添加上面的三个内容
            var todayContent = "<div class='todayHeader'>任务统计</div>"
            todayContent += "<div class='counters'>"
            if (done == true) {
                todayContent += "<div class='counter' id='done'><div class='count'>" + doneCount + "</div><div class='label'>已完成</div></div>"
            }
            todayContent += "<div class='counter' id='overdue'><div class='count'>" + overdueCount + "</div><div class='label'>逾期的</div></div>"
            todayContent += "<div class='counter' id='process'><div class='count'>" + processCount + "</div><div class='label'>处理中</div></div>"
            todayContent += "</div>"
            todayContent += "<div class='motivation'>" + motivation + "</div>"

            content += todayContent;
        };

        // Set Date Template
        var date = "<div class='dateLine'><div class='date'>" + date + "</div><div class='relative'>" + relative + "</div></div><div class='content'>" + content + "</div>"

        // 一个任务信息
        rootNode.querySelector("span").appendChild(dv.el("div", date, {cls: "details " + detailsCls, attr: {"data-year": year}}));
    };
};
